import base64
import urllib
import requests
import json
import time
from django.conf import settings
from utils.myRedis import myRedis
from utils.baidu_config import BaiduConfig
import os
import cv2


class BaiduAIConfig:
    """百度智能云配置类"""
    
    def __init__(self, service='default'):
        # 使用配置管理类
        self.config = BaiduConfig()
        self.API_KEY = self.config.get_api_key(service)
        self.SECRET_KEY = self.config.get_secret_key(service)
        self.TOKEN_CACHE_KEY = self.config.get_token_cache_config()['key'] + (f'_{service}' if service != 'default' else '')
        self.TOKEN_CACHE_EXPIRE = self.config.get_token_cache_config()['expire']
        # 内存缓存作为备选
        self._memory_cache = {}
    
    def get_access_token(self):
        """
        获取百度AI访问token，优先从缓存获取
        Returns:
            str: access_token
        """
        # 先从Redis缓存获取token
        try:
            cached_token = myRedis.get(self.TOKEN_CACHE_KEY)
            if cached_token:
                return cached_token
        except:
            # Redis不可用时，使用内存缓存
            if self.TOKEN_CACHE_KEY in self._memory_cache:
                token_data = self._memory_cache[self.TOKEN_CACHE_KEY]
                if time.time() < token_data['expire_time']:
                    return token_data['token']
        
        # 缓存中没有，重新获取
        return self._refresh_access_token()
    
    def _refresh_access_token(self):
        """
        刷新百度AI访问token
        Returns:
            str: access_token
        """
        url = "https://aip.baidubce.com/oauth/2.0/token"
        params = {
            "grant_type": "client_credentials",
            "client_id": self.API_KEY,
            "client_secret": self.SECRET_KEY
        }
        try:
            response = requests.post(url, params=params, timeout=10)
            response.raise_for_status()
            result = response.json()
            if 'access_token' in result:
                access_token = result['access_token']
                # 将token缓存到Redis，设置过期时间比百度token有效期短一些
                try:
                    myRedis.set(self.TOKEN_CACHE_KEY, access_token, self.TOKEN_CACHE_EXPIRE)
                except:
                    # Redis不可用时，使用内存缓存
                    self._memory_cache[self.TOKEN_CACHE_KEY] = {
                        'token': access_token,
                        'expire_time': time.time() + self.TOKEN_CACHE_EXPIRE
                    }
                return access_token
            else:
                raise Exception(f"获取token失败: {result}")
        except requests.exceptions.RequestException as e:
            raise Exception(f"网络请求失败: {str(e)}")
        except json.JSONDecodeError as e:
            raise Exception(f"JSON解析失败: {str(e)}")
        except Exception as e:
            raise Exception(f"获取access_token失败: {str(e)}")


class BaiduAIAPI:
    """百度AI API封装类"""
    def __init__(self):
        self.config = BaiduAIConfig()  # 默认服务
        self.idcard_config = BaiduAIConfig(service='idcard')  # 身份证专用
    
    def _make_idcard_request(self, image_base64, side="front"):
        """
        使用新方法发送身份证识别请求
        Args:
            image_base64 (str): 图片base64编码
            side (str): 身份证面，front-正面，back-背面
        Returns:
            dict: API响应结果
        """
        access_token = self.idcard_config.get_access_token()
        url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token={access_token}"
        
        payload = f'id_card_side={side}&image={image_base64}&detect_ps=true&detect_risk=false&detect_quality=false&detect_photo=false&detect_card=false&detect_direction=false'
        
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        }
        
        try:
            response = requests.post(url, headers=headers, data=payload.encode("utf-8"), timeout=30)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f"API请求失败: {str(e)}")
        except json.JSONDecodeError as e:
            raise Exception(f"响应解析失败: {str(e)}")
    
    def _make_ocr_request(self, image_base64):
        """
        使用新方法发送通用文字识别请求
        Args:
            image_base64 (str): 图片base64编码
        Returns:
            dict: API响应结果
        """
        access_token = self.config.get_access_token()
        url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token={access_token}"
        
        payload = f'image={image_base64}&detect_direction=false&paragraph=false&probability=false'
        
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
        }
        
        try:
            response = requests.post(url, headers=headers, data=payload.encode("utf-8"), timeout=30)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise Exception(f"API请求失败: {str(e)}")
        except json.JSONDecodeError as e:
            raise Exception(f"响应解析失败: {str(e)}")
    
    def _get_file_content_as_base64(self, file_path, urlencoded=True):
        """
        获取文件base64编码
        :param file_path: 文件路径
        :param urlencoded: 是否对结果进行urlencoded 
        :return: base64编码信息
        """
        # 修正：如果 file_path 以 /uploads/ 开头，则用 MEDIA_ROOT 拼接
        if file_path.startswith('/uploads/'):
            file_path = os.path.join(settings.MEDIA_ROOT, file_path.lstrip('/uploads/'))
        with open(file_path, "rb") as f:
            content = base64.b64encode(f.read()).decode("utf8")
            if urlencoded:
                content = urllib.parse.quote_plus(content)
        return content
    
    def verify_id_card(self, image_path, side="front"):
        """
        身份证识别验证
        Args:
            image_path (str): 身份证图片文件路径
            side (str): 身份证面，front-正面，back-背面
        Returns:
            dict: 识别结果
        """
        try:
            # 获取图片base64编码
            image_base64 = self._get_file_content_as_base64(image_path)
            
            # 发送识别请求
            result = self._make_idcard_request(image_base64, side)
            
            # 检查API返回结果
            if 'error_code' in result:
                return {
                    'success': False,
                    'error_code': result['error_code'],
                    'error_msg': result.get('error_msg', '未知错误'),
                    'data': None
                }
            
            # 解析识别结果
            if 'words_result' in result:
                words_result = result['words_result']
                parsed_data = {}
                if isinstance(words_result, dict):
                    if '姓名' in words_result:
                        parsed_data['name'] = words_result['姓名']['words']
                    if '公民身份号码' in words_result:
                        parsed_data['id_number'] = words_result['公民身份号码']['words']
                    if '性别' in words_result:
                        parsed_data['gender'] = words_result['性别']['words']
                    if '民族' in words_result:
                        parsed_data['ethnicity'] = words_result['民族']['words']
                    if '出生' in words_result:
                        parsed_data['birth_date'] = words_result['出生']['words']
                    if '住址' in words_result:
                        parsed_data['address'] = words_result['住址']['words']
                    if '签发机关' in words_result:
                        parsed_data['issuing_authority'] = words_result['签发机关']['words']
                    if '有效期限' in words_result:
                        parsed_data['valid_period'] = words_result['有效期限']['words']
                return {
                    'success': True,
                    'error_code': None,
                    'error_msg': None,
                    'data': parsed_data,
                    'raw_result': result
                }
            else:
                return {
                    'success': False,
                    'error_code': -1,
                    'error_msg': '识别结果为空',
                    'data': None
                }
        except Exception as e:
            return {
                'success': False,
                'error_code': -1,
                'error_msg': str(e),
                'data': None
            }
    
    def ocr_text_recognition(self, image_path):
        """
        通用文字识别
        
        Args:
            image_path (str): 图片文件路径
            
        Returns:
            dict: 识别结果
        """
        try:
            # 获取图片base64编码
            image_base64 = self._get_file_content_as_base64(image_path)
            
            # 发送识别请求
            result = self._make_ocr_request(image_base64)
            
            if 'error_code' in result:
                return {
                    'success': False,
                    'error_code': result['error_code'],
                    'error_msg': result.get('error_msg', '未知错误'),
                    'data': None
                }
            
            if 'words_result' in result:
                words_list = [item['words'] for item in result['words_result']]
                return {
                    'success': True,
                    'error_code': None,
                    'error_msg': None,
                    'data': {
                        'words_list': words_list,
                        'words_count': len(words_list)
                    },
                    'raw_result': result
                }
            else:
                return {
                    'success': False,
                    'error_code': -1,
                    'error_msg': '识别结果为空',
                    'data': None
                }
                
        except Exception as e:
            return {
                'success': False,
                'error_code': -1,
                'error_msg': str(e),
                'data': None
            }
    
    def verify_id_card_complete(self, front_image_path, back_image_path):
        """
        完整身份证验证（正反面）
        
        Args:
            front_image_path (str): 身份证正面图片文件路径
            back_image_path (str): 身份证背面图片文件路径
            
        Returns:
            dict: 验证结果
        """
        # 识别正面
        front_result = self.verify_id_card(front_image_path, "front")
        if not front_result['success']:
            return front_result
        
        # 识别背面
        back_result = self.verify_id_card(back_image_path, "back")
        if not back_result['success']:
            return back_result
        
        # 合并结果
        combined_data = {
            'front_data': front_result['data'],
            'back_data': back_result['data']
        }
        
        # 验证身份证号码一致性
        front_id = front_result['data'].get('id_number', '')
        back_id = back_result['data'].get('id_number', '')
        
        if front_id and back_id and front_id != back_id:
            return {
                'success': False,
                'error_code': -1,
                'error_msg': '身份证正反面号码不一致',
                'data': combined_data
            }
        
        return {
            'success': True,
            'error_code': None,
            'error_msg': None,
            'data': combined_data
        }


    def recognize_id_card(self, image_url):
        """
        从URL识别身份证信息
        Args:
            image_url (str): 身份证图片URL
        Returns:
            dict: 识别结果，包含name和code
        """
        try:
            # 下载图片
            response = requests.get(image_url, timeout=30)
            response.raise_for_status()
            
            # 将图片内容转为base64
            image_base64 = base64.b64encode(response.content).decode('utf-8')
            image_base64 = urllib.parse.quote_plus(image_base64)
            
            # 发送识别请求
            result = self._make_idcard_request(image_base64, "front")
            
            # 检查API返回结果
            if 'error_code' in result:
                return {
                    'success': False,
                    'error': f"API错误: {result.get('error_msg', '未知错误')}"
                }
            
            # 解析识别结果
            if 'words_result' in result:
                words_result = result['words_result']
                name = None
                code = None
                
                for item in words_result:
                    if 'name' in item:
                        name = item['name']['words']
                    elif '公民身份号码' in item:
                        code = item['公民身份号码']['words']
                
                if name and code:
                    return {
                        'success': True,
                        'name': name,
                        'code': code
                    }
                else:
                    return {
                        'success': False,
                        'error': '未能识别姓名或身份证号'
                    }
            else:
                return {
                    'success': False,
                    'error': '识别结果格式错误'
                }
                
        except requests.exceptions.RequestException as e:
            return {
                'success': False,
                'error': f'图片下载失败: {str(e)}'
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'识别失败: {str(e)}'
            }

    def extract_face_from_idcard(self, image_path):
        """
        使用百度人脸检测API自动提取身份证图片中的人脸并保存为新图片，返回保存路径。
        Args:
            image_path (str): 身份证图片文件路径
        Returns:
            dict: {'success': True, 'face_path': ...} 或 {'success': False, 'msg': ...}
        """
        try:
            # 1. 获取access_token
            access_token = self.idcard_config.get_access_token()
            # 2. 读取图片base64
            with open(image_path, 'rb') as f:
                img_base64 = base64.b64encode(f.read()).decode()
            # 3. 调用百度人脸检测API
            url = f'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token={access_token}'
            headers = {'Content-Type': 'application/json'}
            data = {
                'image': img_base64,
                'image_type': 'BASE64',
                'face_field': 'faceshape,facetype',
                'max_face_num': 1
            }
            resp = requests.post(url, headers=headers, json=data, timeout=30)
            result = resp.json()
            # 4. 解析人脸框并裁剪保存
            if result.get('error_code') == 0 and result.get('result', {}).get('face_num', 0) > 0:
                face = result['result']['face_list'][0]
                location = face['location']
                left = int(location['left'])
                top = int(location['top'])
                width = int(location['width'])
                height = int(location['height'])
                img = cv2.imread(image_path)
                if img is None:
                    return {'success': False, 'msg': f'图片无法读取，请确保路径无中文且图片有效: {image_path}'}
                # 边界保护
                h, w, _ = img.shape
                x1 = max(0, left)
                y1 = max(0, top)
                x2 = min(w, left + width)
                y2 = min(h, top + height)
                face_img = img[y1:y2, x1:x2]
                face_path = image_path.replace('.jpg', '_face.jpg').replace('.png', '_face.png')
                cv2.imwrite(face_path, face_img)
                return {'success': True, 'face_path': face_path}
            else:
                return {'success': False, 'msg': f"未检测到人脸: {result.get('error_msg', '未知错误')}"}
        except Exception as e:
            return {'success': False, 'msg': str(e)}

    def face_match(self, image_path1, image_path2):
        """
        人脸对比
        image_path1: 身份证头像图片路径
        image_path2: 用户自拍照图片路径
        """
        import base64, json, requests
        access_token = self.idcard_config.get_access_token()
        url = f"https://aip.baidubce.com/rest/2.0/face/v3/match?access_token={access_token}"

        def img_to_base64(path):
            with open(path, 'rb') as f:
                return base64.b64encode(f.read()).decode()

        data = [
            {"image": img_to_base64(image_path1), "image_type": "BASE64", "face_type": "CERT", "quality_control": "NORMAL", "liveness_control": "NONE"},
            {"image": img_to_base64(image_path2), "image_type": "BASE64", "face_type": "LIVE", "quality_control": "NORMAL", "liveness_control": "NORMAL"}
        ]
        headers = {'Content-Type': 'application/json'}
        resp = requests.post(url, headers=headers, data=json.dumps(data))
        result = resp.json()
        if result.get('error_code') == 0:
            score = result['result']['score']
            return {'success': True, 'score': score, 'raw': result}
        else:
            return {'success': False, 'msg': result.get('error_msg', '对比失败'), 'raw': result}

# 创建全局实例
baidu_ai = BaiduAIAPI()

def analyze_resume(file_path):
    """
    模拟AI分析简历内容，实际可调用百度AI等接口。
    :param file_path: 简历文件路径
    :return: 分析结果字典
    """
    # 这里可以集成OCR、NLP等AI分析逻辑
    return {
        "学历": "本科",
        "专业": "计算机科学与技术",
        "技能": ["Python", "Django", "机器学习"],
        "工作经验": "3年",
        "自我评价": "学习能力强，适应新环境快"
    }



